﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TestApp
{
    public class DPolygon:Shape
    {
         private Polygon _polyline;
        private PointCollection Points = new PointCollection();
        private List<Ellipse> _joinPoints = new List<Ellipse>();
        private List<Rectangle> _rectangles = new List<Rectangle>();
        private Canvas _parent;
        private bool IsCompleted;
         
        double x = 0.0;
        double y = 0.0; 
         
        public event EventHandler<DrawEventArgs> PolylineEndDrawed;
        public event EventHandler<DrawEventArgs> PointDrawed;
        public int drawType = 0;
        public DPolygon()
        {

            
            this.Loaded += (s, e) => InitVisualize();
            
            PointDrawed += (s,e) => 
            {
                DrawJoinPoint(e.CurrentPoint, Colors.Red, Colors.Black, 5, 3);
                
            };
        }

        

        private void InitVisualize()
        {
            try
            {
                _parent = this.Parent as Canvas;
            }
            catch (Exception)
            {
                throw new Exception("DPolyLine 的父元素应该指定为Canvas类型！");
            }
            _polyline = new Polygon();
            _polyline.StrokeThickness = this.StrokeThickness;
            _polyline.StrokeLineJoin = this.StrokeLineJoin;
            _polyline.StrokeDashCap = this.StrokeDashCap;
            _polyline.StrokeEndLineCap = this.StrokeEndLineCap;
            _polyline.StrokeStartLineCap = this.StrokeStartLineCap;
            _polyline.Fill = this.Fill == null ? new SolidColorBrush(Color.FromArgb(0x88, 0xff, 0xff, 0x00)) : this.Fill;
            _polyline.Stroke = this.Stroke == null ? new SolidColorBrush(Colors.Red) : this.Stroke;
            _polyline.StrokeThickness = _polyline.StrokeThickness < 1 ? 1.0 : _polyline.StrokeThickness;
            _polyline.Points = this.Points;
            _polyline.MouseLeftButtonDown += new MouseButtonEventHandler(pline_MouseLeftButtonDown);
            _parent.Children.Add(_polyline);

            _parent.MouseLeftButtonDown += new MouseButtonEventHandler(_parent_MouseLeftButtonDown);
            _parent.MouseMove += new MouseEventHandler(_parent_MouseMove);
            _parent.MouseLeftButtonUp += new MouseButtonEventHandler(_parent_MouseLeftButtonUp);

        }

        private void pline_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Polygon item = sender as Polygon;
            y = e.GetPosition(null).Y;
            x = e.GetPosition(null).X;
            //isMove = true;
            CreatMenu(item);
            item.CaptureMouse(); 
            item.Stroke = new SolidColorBrush(Colors.Black);
            item.StrokeThickness = 3;
           
        }



        #region 创建右键菜单
        private void CreatMenu(Polygon item)
        {
            ContextMenu cm = new ContextMenu();
            MenuItem m1 = new MenuItem();
            m1.Header = "复制";
            m1.Click += new RoutedEventHandler(Copy_Click);
            cm.Items.Add(m1);

            MenuItem m2 = new MenuItem();
            m2.Header = "修改";
            m2.Click += new RoutedEventHandler(Modify_Click);
            cm.Items.Add(m2);
            MenuItem m3 = new MenuItem();
            m3.Header = "删除";
            m3.Click += new RoutedEventHandler(Del_Click);
            cm.Items.Add(m3);

            ContextMenuService.SetContextMenu(item, cm);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Del_Click(object sender, RoutedEventArgs e)
        {
            _parent.Children.Remove(_polyline);
        }

        /// <summary>
        /// 在图片上点击修改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Modify_Click(object sender, RoutedEventArgs e)
        {

        }

        private void Copy_Click(object sender, RoutedEventArgs e)
        {

        }
        #endregion
        private void _parent_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (IsCompleted) {
                FrameworkElement element = sender as FrameworkElement;
                element.ReleaseMouseCapture();
                IsCompleted = false;
            }
        }

        private void _parent_MouseMove(object sender, MouseEventArgs e)
        {
            LastPoint = e.GetPosition(_parent);
            if (CheckCompleted())
            {
                _parent.Cursor = Cursors.Hand;
                FrameworkElement element = sender as FrameworkElement;
                element.ReleaseMouseCapture();
                IsCompleted = true;
               
            }
            else
            {
                _parent.Cursor = Cursors.Arrow;
            }
        }

        private void _parent_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        { 

            DrawEventArgs args = new DrawEventArgs(); 
           
            if (!CheckCompleted())
            {


                if (Points.Count == 0)
                {
                    if (LastPoint.X > e.GetPosition(_parent).X && LastPoint.Y > e.GetPosition(_parent).Y)
                    {
                        Points.Add(e.GetPosition(_parent));
                        args.CurrentPoint = Points[0];
                        //画点
                        if (PointDrawed != null)
                            PointDrawed(sender, args);
                    }
                }
                else
                {


                    Points[Points.Count - 1] = LastPoint;
                    args.CurrentPoint = LastPoint;
                    if (PointDrawed != null)
                        PointDrawed(sender, args);

                }
            }
            else {
                
                    LastPoint = Points[0];
                    //IsCompleted = true;
                    if (PolylineEndDrawed != null)
                    {
                        args.Points = GetPoints();
                        PolylineEndDrawed(sender, args);
                    }
                    Points.Add(e.GetPosition(_parent));
                    Points = new PointCollection();
                    _polyline = new Polygon();
                    _polyline.StrokeThickness = this.StrokeThickness;
                    _polyline.StrokeLineJoin = this.StrokeLineJoin;
                    _polyline.StrokeDashCap = this.StrokeDashCap;
                    _polyline.StrokeEndLineCap = this.StrokeEndLineCap;
                    _polyline.StrokeStartLineCap = this.StrokeStartLineCap;
                    _polyline.Fill = this.Fill == null ? new SolidColorBrush(Color.FromArgb(0x88, 0xff, 0xff, 0x00)) : this.Fill;
                    _polyline.Stroke = this.Stroke == null ? new SolidColorBrush(Colors.Red) : this.Stroke;
                    _polyline.StrokeThickness = _polyline.StrokeThickness < 1 ? 1.0 : _polyline.StrokeThickness;
                    _polyline.Points = this.Points;
                    _polyline.MouseLeftButtonDown += new MouseButtonEventHandler(pline_MouseLeftButtonDown);
                    _parent.Children.Add(_polyline);
                    return;
                
            }
            Points.Add(e.GetPosition(_parent));
            

        }

        public void ClearCanvas()
        {
            this.Points.Clear();
            foreach (Ellipse e in _joinPoints)
            {
                _parent.Children.Remove(e);
            }
            _joinPoints.Clear();
            IsCompleted = false;
        }
        
        private void DrawJoinPoint(Point p,Color fill,Color stoke,double radio,double lineThickness)
        {

             
                Ellipse e = new Ellipse();
                e.Fill = new SolidColorBrush(fill);
                e.Stroke = new SolidColorBrush(stoke);
                e.Height = e.Width = radio + lineThickness;
                e.StrokeThickness = lineThickness;

                e.SetValue(Canvas.LeftProperty, p.X - e.Width / 2);
                e.SetValue(Canvas.TopProperty, p.Y - e.Height / 2);

                _parent.Children.Add(e);
                if (!IsCompleted)
                {
                    _joinPoints.Add(e);
                }
        }

        private bool CheckCompleted()
        {
            return Points.Count > 0 && Math.Abs(Points[0].X - LastPoint.X) < 5 && Math.Abs(Points[0].Y - LastPoint.Y) < 5;
        }

        private static DependencyProperty LastPointProperty = DependencyProperty.Register(
            "LastPoint", typeof(Point), typeof(DPolygon),
            new PropertyMetadata(new PropertyChangedCallback(LastPointChanged)));

        public Point LastPoint
        {
            get { return (Point)GetValue(LastPointProperty); }
            set { SetValue(LastPointProperty, value); }
        }

        public static void LastPointChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            //DPolygon poly = sender as DPolygon;
            //if (!poly.IsCompleted && poly.Points.Count > 0)
            //{
            //    poly.Points[poly.Points.Count - 1] = (Point)e.NewValue;
            //}
        }

        public List<Point> GetPoints()
        {
            List<Point> points = new List<Point>(Points.Count);
            foreach (Point p in Points)
                points.Add(p);
            return points;
        }

    }
}
